# cython: language_level=3
from datetime import datetime

from sqlalchemy import select, func
from sqlalchemy.orm import Session

from app.db.sql.intra_day_task import get_resource_rtd
from app.models.operator import Operator
from app.models.resource import Resource
from app.schemas.update_resource import UpdateResourceRequest
from common.log import get_logger
from common.redis import MyRedis

logger = get_logger("server")


def get_resources_by_credit_code(
        db: Session, credit_code: str, page: int, page_size: int
):
    operator = db.scalars(select(Operator).filter_by(credit_code=credit_code)).first()
    if not operator:
        return {"page": page, "totalPage": 1, "realData": []}
    offset_size = page_size * (page - 1)
    find_sql = select(Resource).filter_by(operator_id=operator.id)
    total_count = db.scalars(
        select(func.count("*")).select_from(Resource).filter_by(operator_id=operator.id)
    ).one()
    # logger.info("total_count = ", total_count)
    results = db.scalars(find_sql.offset(offset_size).limit(page_size)).all()
    ret_data = []
    """
    responseLevel
    响应时间级别，
    响应一级（响应时间≤1秒以内达到响应目标）：1 
    响应二级（1秒＜响应时间≤1分钟以内达到响应目标）：2 
    响应三级（ 1分钟＜响应时间≤15分钟以内达到响应目标）：3
    响应四级（15分钟＜响应时间≤30分钟以内达到响应目标） ：4
    响应五级（30分钟＜响应时间≤2小时以内达到响应目标）：5 
    响应六级（2小时＜响应时间≤24小时以内达到响应目标）：6  
    响应七级（≥24小时以内达到响应目标）：7 
    """
    for result in results:
        ret_data.append(
            {
                "resourceId": result.resource_id,
                "resourceName": result.resource_name,
                "resourceType": result.resource_type,
                "responseType": 1,  # 响应方式，传编码值（1：自动响应，0：人工响应）
                "resourceState": result.resource_state,  # 资源状态，传编码值（2表示测试，3表示投运，4表示退役，5表示停机）
                "maxAdjustablePower": result.max_adjustable_power,
                "increaseRate": 0,  # 最大上升速率（kW/min）
                "decreaseRate": 0,  # 最大下降速率（kW/min）
                "responseLevel": 1,  # 响应时间级别
                "deviceNum": 1,  # 该resourceID下挂设备数量(充电站填充电桩数量，换电站填电池数量，建筑楼宇填空调主机数量，铁塔基站/分布式光伏及其他均填1)
                "longitude": result.longitude,
                "latitude": result.latitude,
                "address": "",  # 用电地址
                "parentSourceId": result.parent_resource_id,
            }
        )
    return {
        "page": page,
        "totalPage": total_count // page_size + 1,
        "resources": ret_data[:page_size],
    }


def get_real_time_data(db: Session, payload, page: int, page_size: int, redis: MyRedis):
    now = datetime.now()
    real_data = []
    offset_size = page_size * (page - 1)
    total_count = db.scalars(select(func.count("*")).select_from(Resource)).one()
    resources = db.scalars(select(Resource).offset(offset_size).limit(page_size)).all()
    for resource in resources:
        rtd = get_resource_rtd(resource.resource_id, redis)
        if rtd is None or resource.resource_state != "3":
            real_data.append(
                {
                    "dateTime": now.strftime(
                        "%Y-%m-%d %H:%M:00"
                    ),  # 采集数据时间(yyyy-MM-dd HH:mm:00)
                    "resourceId": resource.resource_id,
                    "resourceName": resource.resource_name,
                    "maxupCapacity": 0,  # 当前时刻，资源最大上调调节能力(单位kW)
                    "maxupRate": 0,  # 当前时刻，资源最大上调调节速率(单位kW/min)
                    "maxupLength": 0,  # 当前时刻，资源最大上调持续时长(分钟)
                    "maxdownCapacity": 0,  # 当前时刻，资源最大下调调节能力(单位kW)
                    "maxdownRate": 0,  # 当前时刻，资源最大下调调节速率(单位kW/min)
                    "maxdownLength": 0,  # 当前时刻，资源最大下调持续时长(分钟)
                    "controlState": 0,  # 若状态无变化，则不传，资源受控状态，0：受控中，1：待控中；2：旁路中，若下列4个状态无变化，则为null
                    "statusChangeTime": None,
                    "status": "OFFLINE",  # 若状态无变化，则不传，resourceId对应资源的采集终端是否在线，取值范围：ONLINE、OFFLINE。
                    "responseType": str(resource.resource_type),
                    "resourceState": str(
                        resource.resource_state
                    ),  # 若状态无变化，则不传，resourceId对应资源的状态，传编码值（2表示测试，3表示投运，4表示退役，5表示停机）
                    "data": {},
                }
            )
        else:
            real_data.append(
                {
                    "dateTime": now.strftime(
                        "%Y-%m-%d %H:%M:00"
                    ),  # 采集数据时间(yyyy-MM-dd HH:mm:00)
                    "resourceId": resource.resource_id,
                    "resourceName": resource.resource_name,
                    "maxupCapacity": (
                        rtd["maxupCapacity"] if rtd.get("maxupCapacity") is not None else 0
                    ),  # 当前时刻，资源最大上调调节能力(单位kW)
                    "maxupRate": (
                        rtd["maxupRate"] if rtd.get("maxupRate") is not None else 0
                    ),  # 当前时刻，资源最大上调调节速率(单位kW/min)
                    "maxupLength": (
                        rtd["maxupLength"] if rtd.get("maxupLength") is not None else 0
                    ),  # 当前时刻，资源最大上调持续时长(分钟)
                    "maxdownCapacity": (
                        rtd["maxdownCapacity"]
                        if rtd.get("maxdownCapacity") is not None
                        else 0
                    ),  # 当前时刻，资源最大下调调节能力(单位kW)
                    "maxdownRate": (
                        rtd["maxdownRate"] if rtd.get("maxdownRate") is not None else 0
                    ),  # 当前时刻，资源最大下调调节速率(单位kW/min)
                    "maxdownLength": (
                        rtd["maxdownLength"] if rtd.get("maxdownLength") is not None else 0
                    ),  # 当前时刻，资源最大下调持续时长(分钟)
                    "controlState": (
                        rtd["controlState"] if rtd.get("controlState") is not None else "1"
                    ),  # 若状态无变化，则不传，资源受控状态，0：受控中，1：待控中；2：旁路中，若下列4个状态无变化，则为null
                    "statusChangeTime": None,
                    "status": "ONLINE",  # 若状态无变化，则不传，resourceId对应资源的采集终端是否在线，取值范围：ONLINE、OFFLINE。
                    "responseType": str(resource.resource_type),
                    "resourceState": str(
                        resource.resource_state
                    ),  # 若状态无变化，则不传，resourceId对应资源的状态，传编码值（2表示测试，3表示投运，4表示退役，5表示停机）
                    "data": rtd.get("data"),
                }
            )
    return {
        "page": page,
        "totalPage": total_count // page_size + 1,
        "realData": real_data[:page_size],
    }


def find_or_create_resource(db: Session, payload: UpdateResourceRequest):
    resource = db.scalars(
        select(Resource).filter_by(resource_id=payload.resourceId)
    ).first()
    operator = db.scalars(
        select(Operator).filter_by(credit_code=payload.operatorCode)
    ).first()
    if not operator:
        return None
    if not resource:
        resource = Resource(
            resource_id=payload.resourceId,
            resource_name=payload.resourceName,
            resource_type=payload.resourceType,
            resource_state=payload.resourceState,
            max_adjustable_power=payload.maxAdjustablePower,
            assessment_meterbox=payload.assesmentMeterbox,
            listing_num=payload.listingNumber,
            rated_capacity=payload.RatedCapacity,
            rated_power=payload.RatedPower,
            rated_voltage=payload.RatedVoltage,
            longitude=payload.Longitude,
            latitude=payload.Latitude,
            operator_id=str(operator.id),
            create_time=datetime.now(),
            resource_host=payload.resourceHost,
        )
        db.add(resource)
        db.commit()
    else:
        resource.resource_name = payload.resourceName
        resource.resource_type = payload.resourceType
        resource.resource_state = payload.resourceState
        resource.max_adjustable_power = payload.maxAdjustablePower
        resource.assessment_meterbox = payload.assesmentMeterbox
        resource.listing_num = payload.listingNumber
        resource.rated_capacity = payload.RatedCapacity
        resource.rated_power = payload.RatedPower
        resource.rated_voltage = payload.RatedVoltage
        resource.longitude = payload.Longitude
        resource.latitude = payload.Latitude
        resource.resource_host = payload.resourceHost
        db.commit()
    return resource


def find_resource_by_resource_id(db: Session, resourceId: str):
    resource = db.scalars(
        select(Resource).filter_by(resource_id=resourceId)
    ).first()
    return resource
